﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation;

namespace CardGame
{
    /// <summary>
    /// 卡片3D模型
    /// </summary>
    class Card3DModel : Viewport3D
    {
        #region 卡片属性

        private double width = 0; //宽
        private double height = 0; //高
        private double view = 0; //视野
        private Point3D center = new Point3D(); //中心点坐标
        private Point3D[] points = new Point3D[4]; //面座标，共四个点
        private Model3DGroup cardGroup = new Model3DGroup(); //一张卡片为一个组
        private MeshGeometry3D cardForm = new MeshGeometry3D(); //卡片的外观，一个矩形
        private GeometryModel3D geometryModel = new GeometryModel3D(); //几何模型

        #endregion

        #region 动画属性

        private FrameworkElement element = new FrameworkElement();
        private Storyboard story = new Storyboard();
        private DoubleAnimation animation = new DoubleAnimation();
        private AxisAngleRotation3D rotation = new AxisAngleRotation3D(new Vector3D(0, 0, 0), 0); //转轴类
        private Point3D axisCenter = new Point3D();  //轴心 
        private Vector3D axis = new Vector3D(0, 1, 0); //转轴
        private const double angle = 180; //默认旋转角度
        private Duration period = new Duration(TimeSpan.FromMilliseconds(500)); //默认动画周期
        private bool isBegining = false; //动画状态 true 为播放中

        #endregion 

        #region 外部接口

        /// <summary>
        /// 卡片状态（false 表示盖着）
        /// </summary>
        private bool status = false;
        /// <summary>
        /// 获取或设置卡片状态（false 表示盖着）
        /// </summary>
        public bool Status
        {
            get { return status; }
            set { status = value; }
        }

        /// <summary>
        /// 允许表示鼠标点击播放动画
        /// </summary>
        private bool allowMouse = false;
        /// <summary>
        /// 获取或设置允许表示鼠标点击播放动画
        /// </summary>
        public bool AllowMouse
        {
            get { return allowMouse; }
            set { allowMouse = value; }
        }

        /// <summary>
        /// 正面材质
        /// </summary>
        private Brush frontBrush;
        /// <summary>
        /// 获取或设置正面材质
        /// </summary>
        public Brush FrontBrush
        {
            get { return frontBrush; }
            set
            {
                Brush fbrush = value == null ? null : value.Clone();
                geometryModel.Material = new DiffuseMaterial(fbrush);
                frontBrush = value;
            }
        }

        /// <summary>
        /// 背面材质
        /// </summary>
        private Brush backBrush;
        /// <summary>
        /// 获取或设置背面材质
        /// </summary>
        public Brush BackBrush
        {
            get { return backBrush; }
            set
            {
                Brush bBrush = value == null ? null : value.Clone();
                geometryModel.BackMaterial = new DiffuseMaterial(bBrush);
                if (bBrush != null) bBrush.RelativeTransform = new ScaleTransform(-1, 1, 0.5, 0.5); //将背景图片倒置 
                backBrush = value;
            }
        }

        /// <summary>
        /// 卡片翻转后是否触发事件
        /// </summary>
        private bool isCompleted = true;
        /// <summary>
        /// 获取或设置卡片翻转后是否触发事件
        /// </summary>
        public bool IsCompleted
        {
            get { return isCompleted; }
            set { isCompleted = value; }
        }

        /// <summary>
        /// 无参数构造器
        /// </summary>
        public Card3DModel()
            : this(new Point3D(0, 0, 0), 1, 2)
        {
        }

        /// <summary>
        /// 带参数的构造器
        /// </summary>
        /// <param name="pCenter">中心坐标</param>
        /// <param name="pWidth">宽度</param>
        /// <param name="pHeight">高度</param>
        public Card3DModel(Point3D pCenter, double pWidth, double pHeight)
            : this(pCenter, pWidth, pHeight, pHeight * 2)
        { }

        /// <summary>
        /// 带参数的构造器
        /// </summary>
        /// <param name="pCenter">中心坐标</param>
        /// <param name="pWidth">宽度</param>
        /// <param name="pHeight">高度</param>
        /// <param name="pView">视野</param>
        public Card3DModel(Point3D pCenter, double pWidth, double pHeight, double pView)
        {
            NameScope.SetNameScope(element, new NameScope());

            center.X = pCenter.X;
            center.Y = pCenter.Y;
            center.Z = pCenter.Z;

            width = pWidth;

            height = pHeight;

            view = pView;
        }

        /// <summary>
        /// 创建模型
        /// </summary>
        public void Create3DCard()
        {
            InitCamera();
            InitLight();
            InitPoints();
            InitCardForm();
            InitIndices();
            InitTexture();
            InitAxisCenter();
            InitCard3DModel();
            InitStoryboard();
        }

        /// <summary>
        /// 旋转卡片
        /// </summary>
        /// <returns></returns>
        public bool TurnCardOver()
        {
            if (isBegining == false)
            {
                isBegining = true; //进入动画

                // 如果当前角度是360度则设置为 0 度
                if (rotation.Angle % 360 == 0)
                {
                    rotation.Angle = 0;
                    animation.From = 0;
                    animation.To = 180;
                }
                else //否则设为 180 度
                {
                    rotation.Angle = 180;
                    animation.From = 180;
                    animation.To = 360;
                }
                //启动动画
                story.Begin(element);

                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 卡片翻转结束事件，可通过属性 isCompleted 设置是否触发此事件默认为 ture，且每次事件结束后都重置为 ture
        /// </summary>
        public EventHandler TurnCardCompleted = null;

        #endregion

        #region 初始化函数

        //初始化摄像机
        private void InitCamera()
        {
            PerspectiveCamera pc = new PerspectiveCamera();
            pc.Position = new Point3D(0, 0, view);
            pc.LookDirection = new Vector3D(0, 0, -view);

            Camera = pc;
        }
        //初始化环境光
        private void InitLight()
        {
            ModelVisual3D mv = new ModelVisual3D();
            AmbientLight al = new AmbientLight();
            al.Color = Colors.White;
            mv.Content = al;

            Children.Add(mv);
        }
        //初始化四个顶点坐标
        private void InitPoints()
        {
            points[0] = new Point3D(center.X - (width / 2), center.Y + (height / 2), center.Z);
            points[1] = new Point3D(center.X - (width / 2), center.Y - (height / 2), center.Z);
            points[2] = new Point3D(center.X + (width / 2), center.Y - (height / 2), center.Z);
            points[3] = new Point3D(center.X + (width / 2), center.Y + (height / 2), center.Z);
        }
        //初始化外观
        private void InitCardForm()
        {
            cardForm.Positions.Clear();
            for (int i = 0; i < 4; i++)
            {
                cardForm.Positions.Add(points[i]);
            }
        }
        //初始化坐标点顺序
        private void InitIndices()
        {
            cardForm.TriangleIndices.Add(3);
            cardForm.TriangleIndices.Add(2);
            cardForm.TriangleIndices.Add(1);
            cardForm.TriangleIndices.Add(1);
            cardForm.TriangleIndices.Add(0);
            cardForm.TriangleIndices.Add(3);
        }
        //初始化纹理坐标
        private void InitTexture()
        {
            cardForm.TextureCoordinates.Add(new Point(1, 0));
            cardForm.TextureCoordinates.Add(new Point(1, 1));
            cardForm.TextureCoordinates.Add(new Point(0, 1));
            cardForm.TextureCoordinates.Add(new Point(0, 0)); 
        }
        //初始化轴心转轴
        private void InitAxisCenter()
        {
            axisCenter.X = center.X;
            axisCenter.Y = center.Y;
            axisCenter.Z = center.Z;
        }
        //创建卡片
        private void InitCard3DModel()
        {
            geometryModel.Geometry = cardForm;
            cardGroup.Children.Add(geometryModel);
            //为模型组添加旋转属性
            RotateTransform3D rotate = new RotateTransform3D(rotation, axisCenter);
            cardGroup.Transform = rotate;

            ModelVisual3D model = new ModelVisual3D();
            model.Content = cardGroup;

            Children.Add(model);
        }
        //初始化动画属性
        private void InitStoryboard()
        {
            rotation.Axis = axis;

            animation.Duration = period; //设置旋转耗时
            animation.FillBehavior = FillBehavior.HoldEnd; //设置旋转方式

            element.RegisterName("Rotation", rotation);
            Storyboard.SetTargetName(animation, "Rotation");
            Storyboard.SetTargetProperty(animation, new PropertyPath("(AxisAngleRotation3D.Angle)"));

            story.Children.Add(animation);

            MouseLeftButtonDown += StoryBeginning; //鼠标事件
            story.Completed += StoryCompleted;
        }
        
        #endregion

        #region 动画函数

        //播放动画
        private void StoryBeginning(object sender, EventArgs e)
        {
            if (allowMouse)
            {
                TurnCardOver();
            }
        }
        //结束动画
        private void StoryCompleted(object sender, EventArgs e)
        {
            story.Stop(element); //停止动画
            Status = !Status; //更改状态 
            isBegining = false; //动画结束标志

            if (TurnCardCompleted != null && isCompleted)
            {
                TurnCardCompleted(this, e);
            }
            else
            {
                isCompleted = true; //每次结束后都重置为触发
            }
        }

        #endregion
    }
}
